#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

//int main()
//{
//    pid_t id;
//    sleep(1);
//    printf("Before fork: pid is %d\n", getpid());
//    id = fork();
//    if(id < 0)
//    {
//        perror("fork()");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//        printf("子进程，After fork: fork return:%d\n", id);
//        sleep(1);
//    }
//    else 
//    {
//        //父进程
//        printf("父进程，After fork: fork return:%d\n", id);
//        sleep(1);
//    }
//    
//    return 0;
//}

//int main()
//{
//    int i = 0;
//    for(i; i < 200; ++i)
//    {
//        printf("%d -> %s\n", i, strerror(i));
//    }
//    return 0;
//}


//int main()
//{
//    printf("hello linux\n");
//    // _exit(-1);//虽然status是int，但是仅有低8位可以被父进程所用。所以_exit(-1)时，在终端执行echo $?时，发现返回值是255。
//    // exit(-1);//exit(-1)与上同理。也就是说，我们所说的退出码，实际指的是exit()或者_exit()参数的低8位。
//    return 0;//return 的返回值也是同理。
//}

//int main()
//{
//    printf("hello linxu\n");
//    sleep(2);
//    _exit(errno);
//    //exit(errno);
//    return 0;
//}

//int main()
//{
//    printf("hello linux");
//    sleep(2);
//    _exit(errno);//是一个系统调用， 不会刷新缓冲区
//    //exit(errno);//是一个库函数，会刷新缓冲区
//    return 0;
//}

//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//        int cnt = 3;
//        while(cnt--)
//        {
//            printf("我是一个子进程，pid:%d，ppid:%d\n", getpid(), getppid());
//            sleep(1);
//        }
//        exit(errno);
//    }
//    else 
//    {
//        //父进程
//        while(1)
//        {
//            
//            pid_t tmp = wait(NULL);//wait等待成功，返回等待成功的子进程的pid，等待失败返回-1。参数是输出型参数，若是不关心子进程的退出状态，可以设置为NULL
//            if(tmp == -1)
//            {
//                printf("等待失败\n");
//                exit(errno);
//            }
//            else 
//            {
//                printf("等待成功，子进程pid:%d\n", tmp );
//                exit(errno);
//            }
//        }
//    }
//    return 0;
//}


//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//        int cnt = 10; 
//        while(cnt--)
//        {
//            printf("我是一个子进程，pid:%d，ppid:%d\n", getpid(), getppid());
//            sleep(1);
//        }
//        exit(1);//退出码故意设置为1，方便观察退出码和wait参数的区别
//    }
//    else 
//    {
//        //父进程
//        while(1)
//        {
//            int status = 0;//子进程退出码不等价与status，只是status的组成部分
//            pid_t tmp = wait(&status);
//            if(tmp == -1)
//            {
//                printf("等待失败\n");
//                exit(errno);
//            }
//            else 
//            {
//                printf("等待成功，子进程pid:%d", tmp);
//                printf("，status:%d，exit code:%d，signal:%d\n", status, (status>>8) & 0xFF, status & 0x7F); 
//                exit(errno);
//            }
//        }
//    }
//    return 0;
//}

//验证等待失败的情况，退出码errno会被设置
//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//            printf("我是一个子进程，pid:%d，ppid:%d\n", getpid(), getppid());
//        exit(1);
//    }
//    else 
//    {
//        sleep(2);
//        //父进程
//        while(1)
//        {
//            int status = 0;//子进程退出码不等价与status，只是status的组成部分
//            pid_t tmp = waitpid(id + 1, &status, 0);//子进程不存在，等待失败
//            if(tmp == -1)
//            {
//                printf("等待失败\n");
//                exit(errno);
//            }
//            else 
//            {
//                printf("等待成功，子进程pid:%d", tmp);
//                printf("，status:%d，exit code:%d，signal:%d\n", status, (status>>8) & 0xFF, status & 0x7F); 
//                exit(errno);
//            }
//        }
//    }
//    return 0;
//}


//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//            printf("我是一个子进程，pid:%d，ppid:%d\n", getpid(), getppid());
//        exit(1);
//    }
//    else 
//    {
//        sleep(2);
//        //父进程
//        while(1)
//        {
//            int status = 0;//子进程退出码不等价与status，只是status的组成部分
//            //pid_t tmp = waitpid(-1, &status, 0);//等待任何子进程，等价于wait(&status);
//            pid_t tmp = waitpid(id, &status, 0);//等待pid为id的指定子进程
//            if(tmp == -1)
//            {
//                printf("等待失败\n");
//                exit(errno);
//            }
//            else 
//            {
//                printf("等待成功，子进程pid:%d", tmp);
//                printf("，status:%d，exit code:%d，signal:%d\n", status, (status>>8) & 0xFF, status & 0x7F); 
//                exit(errno);
//            }
//        }
//    }
//    return 0;
//}

//查看子进程正常退出情况
//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//            printf("我是一个子进程，pid:%d，ppid:%d\n", getpid(), getppid());
//        exit(1);
//    }
//    else 
//    {
//        sleep(10);
//        //父进程
//        while(1)
//        {
//            int status = 0;//子进程退出码不等价与status，只是status的组成部分
//            //pid_t tmp = waitpid(-1, &status, 0);//等待任何子进程，等价于wait(&status);
//            pid_t tmp = waitpid(id, &status, 0);//等待pid为id的指定子进程
//            if(tmp == -1)
//            {
//                printf("等待失败\n");
//                exit(errno);
//            }
//            else 
//            {
//                printf("等待成功，子进程pid:%d\n", tmp);
//                if(WIFEXITED(status))
//                {
//                    printf("子进程正常退出\n");
//                    //printf("status:%d，exit code:%d\n", status, (status>>8) & 0xFF); 
//                    printf("status:%d，exit code:%d\n", status, WEXITSTATUS(status)); 
//                }
//                else 
//                {
//                    printf("子进程异常退出\n");
//                    printf("status:%d，signal:%d\n", status, status & 0x7F);
//                }
//                exit(errno);
//            }
//        }
//    }
//    return 0;
//}


//手动杀死子进程，看看子进程异常退出情况
//int main()
//{
//    pid_t id = fork();
//    if(id < 0)
//    {
//        perror("fork");
//        exit(errno);
//    }
//    else if(id == 0)
//    {
//        //子进程
//        int cnt = 10;
//        while(cnt--)
//        {
//
//            printf("我是一个子进程，pid:%d，ppid:%d\n", getpid(), getppid());
//            sleep(1);
//        }
//        exit(1);
//    }
//    else 
//    {
//        //父进程
//        while(1)
//        {
//            int status = 0;//子进程退出码不等价与status，只是status的组成部分
//            //pid_t tmp = waitpid(-1, &status, 0);//等待任何子进程，等价于wait(&status);
//            pid_t tmp = waitpid(id, &status, 0);//等待pid为id的指定子进程
//            if(tmp == -1)
//            {
//                printf("等待失败\n");
//                exit(errno);
//            }
//            else 
//            {
//                printf("等待成功，子进程pid:%d\n", tmp);
//                if(WIFEXITED(status))
//                {
//                    printf("子进程正常退出\n");
//                    //printf("status:%d，exit code:%d\n", status, (status>>8) & 0xFF); 
//                    printf("status:%d，exit code:%d\n", status, WEXITSTATUS(status)); 
//                }
//                else 
//                {
//                    printf("子进程异常退出\n");
//                    printf("status:%d，signal:%d\n", status, status & 0x7F);
//                }
//                exit(errno);
//            }
//        }
//    }
//    return 0;
//}

//进程的阻塞等待方式 
//int main()
//{
//    pid_t pid;
//    pid = fork();
//    if(pid < 0)
//    {
//        printf("%s fork error\n",__FUNCTION__);
//        return 1;
//    }
//    else if( pid == 0 )
//    {
//        //child
//        printf("child is run, pid is : %d\n",getpid());
//        sleep(5);
//        exit(257);
//    }
//    else
//    {
//        int status = 0;
//        pid_t ret = waitpid(-1, &status, 0);//阻塞式等待，等待5S 
//        printf("this is test for wait\n");
//        if( WIFEXITED(status) && ret == pid )
//        {
//            printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));
//        }
//        else
//        {
//            printf("wait child failed, child signal is :%d\n", status & 0x7F);
//            return 1;
//        }
//    }
//    return 0;
//}

//进程的非阻塞等待方式
typedef void (*FP)();
#define NUM 5
FP taskBar[NUM + 1];
void downLoad()
{
    printf("这是一个下载任务\n");
}
void refresh()
{
    printf("这是一个刷新任务\n");
}
void upLoad()
{
    printf("这是一个上传任务\n");
}
void assignTheTask(FP task)
{
    int i = 0;
    for(i = 0; i < NUM; ++i)
    {
        if(!taskBar[i])
            break;
    }
    if(i == NUM)
    {
        return ;
    }
    taskBar[i] = task;
}
void handler()
{
    int i = 0;
    for(i = 0; taskBar[i]; ++i)
    {
        taskBar[i]();
    }
}
int main()
{
    assignTheTask(downLoad);
    assignTheTask(refresh);
    assignTheTask(upLoad);
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        exit(errno);
    }
    else if(id == 0)
    {
        //child
        int cnt = 3;
        while(cnt--)
        {
            printf("child process,pid:%d\n", getpid());
            sleep(1);
        }
        exit(errno);
    }
    else 
    {
        //parent
        int status = 0;
        while(1)
        {
            pid_t ret = waitpid(-1, &status, WNOHANG);
            if(ret == -1)
            {
                printf("Waiting for failure\n");
                exit(errno);
            }
            else if(ret == 0)
            {
                printf("Child process is running, I can do somethings:\n");
                handler();
                sleep(1);
            }
            else 
            {
                printf("Waiting for success\n");
                if(WIFEXITED(status) && ret == id)
                {
                    printf("Nomal exit of child process, exit code:%d\n", WEXITSTATUS(status));
                    exit(errno);
                }
                else 
                {
                    printf("Child process exit with error, signal:%d\n", status & 0x7F);
                    exit(errno);
                }
            }
        }
    }
    return 0;
}









































































































































































































































































































































